module builtin

@[typedef]
pub struct C.FILE {}

// <string.h>
fn C.memcpy(dest voidptr, const_src voidptr, n usize) voidptr

fn C.memcmp(const_s1 voidptr, const_s2 voidptr, n usize) int

fn C.memmove(dest voidptr, const_src voidptr, n usize) voidptr

fn C.memset(str voidptr, c int, n usize) voidptr

@[trusted]
fn C.calloc(int, int) &u8

fn C.atoi(&char) int

fn C.malloc(int) &u8

fn C.realloc(a &u8, b int) &u8

fn C.free(ptr voidptr)

fn C.mmap(addr_length int, length isize, prot int, flags int, fd int, offset u64) voidptr
fn C.mprotect(addr_length int, len isize, prot int) int

fn C.aligned_alloc(align isize, size isize) voidptr

// windows aligned memory functions
fn C._aligned_malloc(size isize, align isize) voidptr
fn C._aligned_free(voidptr)
fn C._aligned_realloc(voidptr, size isize, align isize) voidptr
fn C._aligned_offset_malloc(size isize, align isize, offset isize) voidptr
fn C._aligned_offset_realloc(voidptr, size isize, align isize, offset isize) voidptr
fn C._aligned_msize(voidptr, align isize, offset isize) isize
fn C._aligned_recalloc(voidptr, num isize, size isize, align isize) voidptr

fn C.VirtualAlloc(voidptr, isize, u32, u32) voidptr
fn C.VirtualProtect(voidptr, isize, u32, &u32) bool

@[noreturn; trusted]
fn C.exit(code int)

fn C.qsort(base voidptr, items usize, item_size usize, cb C.qsort_callback_func)

fn C.strlen(s &char) int

@[trusted]
fn C.isdigit(c int) bool

// stdio.h
fn C.popen(c &char, t &char) voidptr

// <libproc.h>
fn C.proc_pidpath(int, voidptr, int) int

fn C.realpath(const_path &char, resolved_path &char) &char

// fn C.chmod(byteptr, mode_t) int
fn C.chmod(path &char, mode u32) int

fn C.printf(const_format &char, opt ...voidptr) int
fn C.dprintf(fd int, const_format &char, opt ...voidptr) int
fn C.fprintf(fstream &C.FILE, const_format &char, opt ...voidptr) int
fn C.sprintf(str &char, const_format &char, opt ...voidptr) int
fn C.snprintf(str &char, size usize, const_format &char, opt ...voidptr) int
fn C.wprintf(const_format &u16, opt ...voidptr) int

// used by Android for (e)println to output to the Android log system / logcat
pub fn C.android_print(fstream voidptr, format &char, opt ...voidptr)

fn C.sscanf(str &char, const_format &char, opt ...voidptr) int
fn C.scanf(const_format &char, opt ...voidptr) int

fn C.puts(msg &char) int
@[trusted]
fn C.abs(f64) f64

fn C.fputs(msg &char, fstream &C.FILE) int

fn C.fflush(fstream &C.FILE) int

// TODO: define args in these functions
fn C.fseek(stream &C.FILE, offset int, whence int) int

fn C.fopen(filename &char, mode &char) &C.FILE

fn C.fileno(&C.FILE) int

fn C.fread(ptr voidptr, item_size usize, items usize, stream &C.FILE) usize

fn C.fwrite(ptr voidptr, item_size usize, items usize, stream &C.FILE) usize

fn C.fclose(stream &C.FILE) int

fn C.pclose(stream &C.FILE) int

fn C.open(path &char, flags int, mode ...int) int
fn C.close(fd int) int

fn C.strrchr(s &char, c int) &char
fn C.strchr(s &char, c int) &char

// process execution, os.process:
@[trusted]
fn C.GetCurrentProcessId() u32
@[trusted]
fn C._getpid() int
@[trusted]
fn C.getpid() int

@[trusted]
fn C.GetCurrentThreadId() u32
@[trusted]
fn C.gettid() u32

@[trusted]
fn C.getuid() int

@[trusted]
fn C.geteuid() int

fn C.system(cmd &char) int

fn C.posix_spawn(child_pid &int, path &char, file_actions voidptr, attrp voidptr, argv &&char, envp &&char) int

fn C.posix_spawnp(child_pid &int, exefile &char, file_actions voidptr, attrp voidptr, argv &&char, envp &&char) int

fn C.execve(cmd_path &char, args voidptr, envs voidptr) int

fn C.execvp(cmd_path &char, args &&char) int

fn C._execve(cmd_path &char, args voidptr, envs voidptr) int

fn C._execvp(cmd_path &char, args &&char) int

fn C.strcmp(s1 &char, s2 &char) int

@[trusted]
fn C.fork() int

fn C.wait(status &int) int

fn C.waitpid(pid int, status &int, options int) int

@[trusted]
fn C.kill(pid int, sig int) int

fn C.setenv(&char, &char, int) int

fn C.unsetenv(&char) int

fn C.access(path &char, amode int) int

fn C.remove(filename &char) int

fn C.rmdir(path &char) int

fn C.chdir(path &char) int

fn C.rewind(stream &C.FILE) int

fn C.ftell(&C.FILE) isize

fn C.stat(&char, voidptr) int

fn C.lstat(path &char, buf &C.stat) int

fn C.statvfs(const_path &char, buf &C.statvfs) int

fn C.rename(old_filename &char, new_filename &char) int

fn C.fgets(str &char, n int, stream &C.FILE) int

fn C.fgetpos(&C.FILE, voidptr) int

@[trusted]
fn C.sigemptyset() int

fn C.getcwd(buf &char, size usize) &char

@[trusted]
fn C.mktime() int

fn C.gettimeofday(tv &C.timeval, tz &C.timezone) int

@[trusted]
fn C.sleep(seconds u32) u32

// fn C.usleep(usec useconds_t) int
@[trusted]
fn C.usleep(usec u32) int

@[typedef]
pub struct C.DIR {
}

fn C.opendir(&char) &C.DIR

fn C.closedir(dirp &C.DIR) int

// fn C.mkdir(path &char, mode mode_t) int
fn C.mkdir(path &char, mode u32) int

// C.rand returns a pseudorandom integer from 0 (inclusive) to C.RAND_MAX (exclusive)
@[trusted]
fn C.rand() int

// C.srand seeds the internal PRNG with the given value.
@[trusted]
fn C.srand(seed u32)

fn C.atof(str &char) f64

@[trusted]
fn C.tolower(c int) int

@[trusted]
fn C.toupper(c int) int

@[trusted]
fn C.isspace(c int) int

fn C.strchr(s &char, c int) &char

@[trusted]
fn C.getchar() int

@[trusted]
fn C.putchar(int) int

fn C.strdup(s &char) &char

fn C.strncasecmp(s &char, s2 &char, n int) int

fn C.strcasecmp(s &char, s2 &char) int

fn C.strncmp(s &char, s2 &char, n int) int

@[trusted]
fn C.strerror(int) &char

@[trusted]
fn C.WIFEXITED(status int) bool

@[trusted]
fn C.WEXITSTATUS(status int) int

@[trusted]
fn C.WIFSIGNALED(status int) bool

@[trusted]
fn C.WTERMSIG(status int) int

@[trusted]
fn C.isatty(fd int) int

fn C.syscall(number int, va ...voidptr) int

fn C.sysctl(name &int, namelen u32, oldp voidptr, oldlenp voidptr, newp voidptr, newlen usize) int

@[trusted]
fn C._fileno(int) int

pub type C.intptr_t = voidptr

fn C._get_osfhandle(fd int) C.intptr_t

fn C.GetModuleFileName(hModule voidptr, lpFilename &u16, nSize u32) u32

fn C.GetModuleFileNameW(hModule voidptr, lpFilename &u16, nSize u32) u32

fn C.CreateFile(lpFilename &u16, dwDesiredAccess u32, dwShareMode u32, lpSecurityAttributes &u16, dwCreationDisposition u32,
	dwFlagsAndAttributes u32, hTemplateFile voidptr) voidptr

fn C.CreateFileW(lpFilename &u16, dwDesiredAccess u32, dwShareMode u32, lpSecurityAttributes &u16, dwCreationDisposition u32,
	dwFlagsAndAttributes u32, hTemplateFile voidptr) voidptr

fn C.GetFinalPathNameByHandleW(hFile voidptr, lpFilePath &u16, nSize u32, dwFlags u32) u32

fn C.CreatePipe(hReadPipe &voidptr, hWritePipe &voidptr, lpPipeAttributes voidptr, nSize u32) bool

fn C.SetHandleInformation(hObject voidptr, dwMask u32, dw_flags u32) bool

fn C.ExpandEnvironmentStringsW(lpSrc &u16, lpDst &u16, nSize u32) u32

fn C.GetComputerNameW(&u16, &u32) bool

fn C.GetUserNameW(&u16, &u32) bool

@[trusted]
fn C.SendMessageTimeout() isize

fn C.SendMessageTimeoutW(hWnd voidptr, msg u32, wParam &u16, lParam &u32, fuFlags u32, uTimeout u32, lpdwResult &u64) isize

fn C.CreateProcessW(lpApplicationName &u16, lpCommandLine &u16, lpProcessAttributes voidptr, lpThreadAttributes voidptr,
	bInheritHandles bool, dwCreationFlags u32, lpEnvironment voidptr, lpCurrentDirectory &u16, lpStartupInfo voidptr,
	lpProcessInformation voidptr) bool

fn C.ReadFile(hFile voidptr, lpBuffer voidptr, nNumberOfBytesToRead u32, lpNumberOfBytesRead &u32, lpOverlapped voidptr) bool

fn C.GetFileAttributesW(lpFileName &u8) u32

fn C.RegQueryValueEx(hKey voidptr, lpValueName &u16, lp_reserved &u32, lpType &u32, lpData &u8, lpcbData &u32) int

fn C.RegQueryValueExW(hKey voidptr, lpValueName &u16, lp_reserved &u32, lpType &u32, lpData &u8, lpcbData &u32) int

fn C.RegOpenKeyEx(hKey voidptr, lpSubKey &u16, ulOptions u32, samDesired u32, phkResult voidptr) int

fn C.RegOpenKeyExW(hKey voidptr, lpSubKey &u16, ulOptions u32, samDesired u32, phkResult voidptr) int

fn C.RegSetValueEx(hKey voidptr, lpValueName &u16, dwType u32, lpData &u16, cbData u32) int

fn C.RegSetValueExW(hKey voidptr, lpValueName &u16, reserved u32, dwType u32, const_lpData &u8, cbData u32) int

fn C.RegCloseKey(hKey voidptr) int

fn C.RemoveDirectory(lpPathName &u16) bool

fn C.RemoveDirectoryW(lpPathName &u16) bool

fn C.GetStdHandle(u32) voidptr

fn C.SetConsoleMode(voidptr, u32) bool

fn C.GetConsoleMode(voidptr, &u32) bool

@[trusted]
fn C.GetCurrentProcessId() u32

// fn C.setbuf()
fn C.setbuf(voidptr, &char)

fn C.SymCleanup(hProcess voidptr)

fn C.MultiByteToWideChar(codePage u32, dwFlags u32, lpMultiMyteStr &char, cbMultiByte int, lpWideCharStr &u16,
	cchWideChar int) int

fn C.wcslen(str voidptr) usize

fn C.WideCharToMultiByte(codePage u32, dwFlags u32, lpWideCharStr &u16, cchWideChar int, lpMultiByteStr &char,
	cbMultiByte int, lpDefaultChar &char, lpUsedDefaultChar &int) int

fn C._wstat(path &u16, buffer &C._stat) int

fn C._wrename(oldname &u16, newname &u16) int

fn C._wfopen(filename &u16, mode &u16) voidptr

fn C._wpopen(command &u16, mode &u16) voidptr

fn C._pclose(stream &C.FILE) int

fn C._wsystem(command &u16) int

fn C._wgetenv(varname &u16) voidptr

fn C._putenv(envstring &char) int
fn C._wputenv(envstring &u16) int

fn C._waccess(path &u16, mode int) int

fn C._wremove(path &u16) int

fn C.ReadConsole(in_input_handle voidptr, out_buffer voidptr, in_chars_to_read u32, out_read_chars &u32,
	in_input_control voidptr) bool

fn C.WriteConsole() voidptr

fn C.WriteFile(hFile voidptr, lpBuffer voidptr, nNumberOfBytesToWrite u32, lpNumberOfBytesWritten &u32, lpOverlapped voidptr) bool

fn C._wchdir(dirname &u16) int

fn C._wgetcwd(buffer &u16, maxlen int) int

fn C._fullpath() int

fn C.GetFullPathName(voidptr, u32, voidptr, voidptr) u32

@[trusted]
fn C.GetCommandLine() voidptr

fn C.LocalFree(voidptr)

fn C.FindFirstFileW(lpFileName &u16, lpFindFileData voidptr) voidptr

fn C.FindFirstFile(lpFileName &u8, lpFindFileData voidptr) voidptr

fn C.FindNextFile(hFindFile voidptr, lpFindFileData voidptr) int

fn C.FindClose(hFindFile voidptr)

// macro
fn C.MAKELANGID(lgid voidptr, srtid voidptr) int

fn C.FormatMessageW(dwFlags u32, lpSource voidptr, dwMessageId u32, dwLanguageId u32, lpBuffer voidptr,
	nSize u32, arguments ...voidptr) u32

fn C.CloseHandle(voidptr) int

fn C.GetExitCodeProcess(hProcess voidptr, lpExitCode &u32)

@[trusted]
fn C.GetTickCount() i64

@[trusted]
fn C.Sleep(dwMilliseconds u32)

fn C.WSAStartup(u16, &voidptr) int

@[trusted]
fn C.WSAGetLastError() int

fn C.closesocket(int) int

fn C.vschannel_init(&C.TlsContext)

fn C.request(&C.TlsContext, int, &u16, &u8, u32, &&u8, fn (voidptr, isize) voidptr) int

fn C.vschannel_cleanup(&C.TlsContext)

fn C.URLDownloadToFile(int, &u16, &u16, int, int)

@[trusted]
fn C.GetLastError() u32

fn C.CreateDirectory(&u8, int) bool

// win crypto
fn C.BCryptGenRandom(int, voidptr, int, int) int

// win synchronization
fn C.CreateMutex(int, bool, &u8) voidptr

fn C.WaitForSingleObject(voidptr, int) int

fn C.ReleaseMutex(voidptr) bool

fn C.CreateEvent(int, bool, bool, &u8) voidptr

fn C.SetEvent(voidptr) int

fn C.CreateSemaphore(voidptr, int, int, voidptr) voidptr

fn C.ReleaseSemaphore(voidptr, int, voidptr) voidptr

fn C.InitializeSRWLock(voidptr)

fn C.AcquireSRWLockShared(voidptr)

fn C.AcquireSRWLockExclusive(voidptr)

fn C.ReleaseSRWLockShared(voidptr)

fn C.ReleaseSRWLockExclusive(voidptr)

// pthread.h
fn C.pthread_self() usize
fn C.pthread_mutex_init(voidptr, voidptr) int

fn C.pthread_mutex_lock(voidptr) int

fn C.pthread_mutex_unlock(voidptr) int

fn C.pthread_mutex_destroy(voidptr) int

fn C.pthread_rwlockattr_init(voidptr) int

fn C.pthread_rwlockattr_setkind_np(voidptr, int) int

fn C.pthread_rwlockattr_setpshared(voidptr, int) int

fn C.pthread_rwlock_init(voidptr, voidptr) int

fn C.pthread_rwlock_rdlock(voidptr) int

fn C.pthread_rwlock_wrlock(voidptr) int

fn C.pthread_rwlock_unlock(voidptr) int

fn C.pthread_condattr_init(voidptr) int

fn C.pthread_condattr_setpshared(voidptr, int) int

fn C.pthread_condattr_destroy(voidptr) int

fn C.pthread_cond_init(voidptr, voidptr) int

fn C.pthread_cond_signal(voidptr) int

fn C.pthread_cond_wait(voidptr, voidptr) int

fn C.pthread_cond_timedwait(voidptr, voidptr, voidptr) int

fn C.pthread_cond_destroy(voidptr) int

fn C.sem_init(voidptr, int, u32) int

fn C.sem_post(voidptr) int

fn C.sem_wait(voidptr) int

fn C.sem_trywait(voidptr) int

fn C.sem_timedwait(voidptr, voidptr) int

fn C.sem_destroy(voidptr) int

// MacOS semaphore functions
@[trusted]
fn C.dispatch_semaphore_create(i64) voidptr

fn C.dispatch_semaphore_signal(voidptr) i64

fn C.dispatch_semaphore_wait(voidptr, u64) i64

@[trusted]
fn C.dispatch_time(u64, i64) u64

fn C.dispatch_release(voidptr)

// file descriptor based reading/writing
fn C.read(fd int, buf voidptr, count usize) int

fn C.write(fd int, buf voidptr, count usize) int

fn C.close(fd int) int

// pipes
fn C.pipe(pipefds &int) int

fn C.dup2(oldfd int, newfd int) int

// used by gl, stbi, freetype
fn C.glTexImage2D()

// used by ios for println
fn C.WrappedNSLog(str &u8)

// absolute value
@[trusted]
fn C.abs(number int) int

fn C.GetDiskFreeSpaceExA(const_path &char, free_bytes_available_to_caller &u64, total_number_of_bytes &u64, total_number_of_free_bytes &u64) bool

fn C.GetNativeSystemInfo(voidptr)

fn C.sysconf(name int) int

// C.SYSTEM_INFO contains information about the current computer system. This includes the architecture and type of the processor, the number of processors in the system, the page size, and other such information.
@[typedef]
pub struct C.SYSTEM_INFO {
	// workaround: v doesn't support a truely C anon union/struct here
	// union {
	dwOemId u32
	// struct {
	wProcessorArchitecture u16
	wReserved              u16
	//	}
	//}
	dwPageSize                  u32
	lpMinimumApplicationAddress voidptr
	lpMaximumApplicationAddress voidptr
	dwActiveProcessorMask       u32
	dwNumberOfProcessors        u32
	dwProcessorType             u32
	dwAllocationGranularity     u32
	wProcessorLevel             u16
	wProcessorRevision          u16
}

fn C.GetSystemInfo(&C.SYSTEM_INFO)

@[typedef]
pub struct C.SRWLOCK {}
